package casess;

import java.util.concurrent.PriorityBlockingQueue;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: fzykd
 * Date: 2022-10-25
 * Time: 16:41
 */
class MyTask {
    //先描述 在组织 任务中有具体的任务的 有个时间是什么时候执行
    public Runnable runnable;
    public long time;

    public MyTask(Runnable runnable, long alter) {
        this.runnable = runnable;
        //此处传来的应该是一个相对时间
        this.time = alter + System.currentTimeMillis();
    }

    public int compare(MyTask o){
        return (int) (this.time-o.time);
    }

}

//描述完一个任务之后 还要去组织
class MyTimer{
    //使用一个数据结构来管理任务 带有线程安全的阻塞队列
    PriorityBlockingQueue<MyTask> queue = new PriorityBlockingQueue<>();
    //第二 这个数据结构 是基于堆来实现的 那么 堆的排序 在这里没有一个明确的规则 那么 要使用CompareTo来明确比较的规则
    //布置任务

    Object lock = new Object();

    public void schedule(Runnable runnable,long time) throws InterruptedException {
        MyTask myTask = new MyTask(runnable,time);
        queue.put(myTask);
        //这里也是 每当有新的任务进来之后 也要唤醒线程去检查 是否新进来的任务时间更考前
        synchronized (lock){
            lock.notify();
        }
    }

    //写一个构造函数
    public MyTimer(){
        //在构造方法中 要有一个线程 不断的去取出线程来比较时间 是否有时间到了的要去执行
        Thread t = new Thread(()->{
            while (true){
                try {
                    //1.首先 这里存在一个忙等问题 当时间没到 那么线程 就一直塞回去 拿出来 也是在消耗资源的
                    //那么就要设置一个等待时间 wait 和 notify就派上用场
                    MyTask myTask = queue.take();
                    //获取当前时间
                    long curTime = System.currentTimeMillis();
                    //判断当前时间和人物事件 是否匹配
                    if (curTime < myTask.time){
                        //现在时间小于 那么就是还没有到时间 将任务在塞回队列当中
                        queue.put(myTask);
                        //每次塞回去之后 设置一个比较时间
                        synchronized (lock){
                            lock.wait(myTask.time - curTime);
                        }
                    }else {
                        //如果时间到了那么就执行
                        myTask.runnable.run();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
    }

}


//自己实现一个定时器
public class Demo4 {
    public static void main(String[] args) throws InterruptedException {
        MyTimer myTimer = new MyTimer();
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello MyTimer");
            }
        },3000);
    }
}
